using System;
using System.Globalization;
using OpenTap;
using OpenTap.Plugins.Interfaces.PSU;

/// <summary>
/// PowerOn states.
/// </summary>
public enum EPonState
{
    [Scpi("RST")] Rst,  // PowerOn settings are same as the reset state.
    [Scpi("AUTO")] Auto // PowerOn settings are same as Psu had with last turn off.
}

namespace OpenTap.Plugins.Psu
{
    [Display("Keysight N5700 PSU driver", Group: "OpenTap.Plugins", Description: "Keysight N5700 PSU driver")]
    public class PsuN5700 : PsuBase
    {
        public PsuN5700()
        {
            // Initial parameters defaults when adding new instrument to TAP
            PowerOnState = EPonState.Rst;

            LeavePowerOn = false;
            Name = "N5700";
        }

        #region Settings

        [Display(Name: "PowerOn State", Group: "Initial Parameters", Order: 2,
            Description: "AUTO => PowerOn state is same as Psu had with last turn off.\n" +
                         "RST => PowerOn state is same as the reset state. MUST be this, if remote inhibit is in use \n" +
                         "to get inhibit latching feature running success.")]
        public EPonState PowerOnState { get; set; }

        [Display(Name: "Leave power ON", Group: "Close Parameters", Order: 3,
            Description: "Leave power ON")]
        public bool LeavePowerOn { get; set; }

        #endregion

        /// <inheritdoc />
        public override void Open()
        {
            lock (_instrumentLock)
            {
                MaxVoltageV = double.NaN;
                MaxCurrentA = double.NaN;

                if (IsConnected) throw new InvalidOperationException("Psu is already connected!");

                base.Open();

                ScpiCommand("OUTP:PON:STAT " + PowerOnState);
                WaitForOperationComplete();
                var powerOnStateResponse = ScpiQuery("OUTP:PON:STAT?");
                Log.Info("Equipment powerOn state Set(" + PowerOnState + ") Respond(" + powerOnStateResponse + ")");

                if(!LeavePowerOn) Reset();

                MaxVoltageV = ScpiQuery<double>("VOLT? MAX");
                Log.Info("Equipment MAX voltage is: " + MaxVoltageV);

                MaxCurrentA = ScpiQuery<double>("CURR? MAX");
                Log.Info("Equipment MAX current is: " + MaxCurrentA);
            }
        }

        /// <inheritdoc />
        public override void Close()
        {
            lock (_instrumentLock)
            {
                Log.Info("PsuN5700: Close");
                if (LeavePowerOn)
                    base.Close(true);
                else
                    base.Close();
            }
        }

        /// <inheritdoc />
        protected override void ScpiCmd_SetVolt(double voltageVolts, EModule module = EModule.Module1)
        {
            lock (_instrumentLock)
            {
                ScpiCommand("VOLT " + voltageVolts.ToString("#.000", CultureInfo.InvariantCulture) + "");
            }
        }

        /// <inheritdoc />
        public override double GetVoltageLevel(EModule module = EModule.Module1)
        {
            lock (_instrumentLock)
            {
                return ScpiQuery<double>("VOLT?");
            }
        }

        /// <inheritdoc />
        public override double GetVoltageLevelMax(EModule module = EModule.Module1)
        {
            lock (_instrumentLock)
            {
                var value = 0.0;
                var txt = ScpiQuery("VMAX?");
                var temp = txt.Split(' ');
                if( temp.Length > 1)
                    value = double.Parse(temp[1], NumberStyles.Float, CultureInfo.InvariantCulture);
                return value;
            }
        }

        /// <inheritdoc />
        public override void SetOverVoltageLevel(double voltage, EModule module = EModule.Module1)
        {
            lock (_instrumentLock)
            {
                ScpiCommand("VOLT:PROT:LEV " + voltage.ToString("#.000", CultureInfo.InvariantCulture));
            }
        }

        /// <inheritdoc />
        public override double GetOverVoltageLevel(EModule module = EModule.Module1)
        {
            lock (_instrumentLock)
            {
                return ScpiQuery<double>("VOLT:PROT:LEV?");
            }
        }

        /// <inheritdoc />
        public override double GetOverVoltageLevelMax(EModule module = EModule.Module1)
        {
            lock (_instrumentLock)
            {
                return ScpiQuery<double>("VOLT:PROT:LEV? MAX");
            }
        }



        public override void SetPolarity(EPolarity polarity, EModule module = EModule.Module1)
        {
            throw new NotImplementedException();
        }

        public override void SetMeterView(EView view)
        {
            throw new Exception("Command is not supported!");
        }

        /// <inheritdoc />
        protected override void ScpiCmd_SetCurr(double currentAmps, EModule module = EModule.Module1){
            lock (_instrumentLock)
            {
                ScpiCommand("CURR " + currentAmps.ToString("#.000", CultureInfo.InvariantCulture));
            }
        }

        /// <inheritdoc />
        public override double GetCurrentLimit(EModule module = EModule.Module1)
        {
            lock (_instrumentLock)
            {
                return ScpiQuery<double>("CURR?");
            }
        }
    }
}